#pragma once

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Runtime::InteropServices;


#include "RobotSimCon.h"
#include "SimulatorBaseEvents.h"

namespace SimulatorBase {


	/// <summary>
	/// Summary for SimulatorBaseControl
	/// </summary>
	///
	/// WARNING: If you change the name of this class, you will need to change the
	///          'Resource File Name' property for the managed resource compiler tool
	///          associated with all .resx files this class depends on.  Otherwise,
	///          the designers will not be able to interact properly with localized
	///          resources associated with this form.
	public ref class SimulatorBaseControl : public System::Windows::Forms::UserControl
	{
	public:
		SimulatorBaseControl(void)
		{
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//

			robotBase = gcnew RobotSimCon();
		}

		property SimulatorBase::RobotBase^ RobotBase {
			SimulatorBase::RobotBase^ get() {
				return robotBase;
			}
			void set(SimulatorBase::RobotBase^ rb) {
				robotBase = rb;
				this->UpdateRobotBase();
			}
		}


		property Int32 LightSensorPort {
			Int32 get() {
				String^ name = "light-sensor";
				String^ sensorAName = textBoxS1->Text;
				String^ sensorBName = textBoxS2->Text;
				String^ sensorCName = textBoxS3->Text;
				if (textBoxS1->Text->StartsWith(name)) {
					return 0;
				}
				if (textBoxS2->Text->StartsWith(name)) {
					return 1;
				}
				if (textBoxS3->Text->StartsWith(name)) {
					return 2;
				}
				return -1;
			}
		}
		
		property Int32 TouchSensorPort {
			Int32 get() {
				String^ name = "touch-sensor";
				if (textBoxS1->Text->ToLower()->StartsWith(name)) {
					return 0;
				}
				if (textBoxS2->Text->ToLower()->StartsWith(name)) {
					return 1;
				}
				if (textBoxS3->Text->ToLower()->StartsWith(name)) {
					return 2;
				}
				return -1;
			}
		}
		
		property Int32 WheelMotorPort {
			Int32 get() {
				String^ name = "wheel";
				if (textBoxA->Text->CompareTo(name)==0) {
					return 0;
				}
				if (textBoxB->Text->CompareTo(name)==0) {
					return 1;
				}
				if (textBoxC->Text->CompareTo(name)==0) {
					return 2;
				}
			}
		}

		property Int32 SteeringMotorPort {
			Int32 get() {
				String^ name = "steering";
				if (textBoxA->Text->CompareTo(name)==0) {
					return 0;
				}
				if (textBoxB->Text->CompareTo(name)==0) {
					return 1;
				}
				if (textBoxC->Text->CompareTo(name)==0) {
					return 2;
				}
			}
		}

		property Int32 SensorS1{
			Int32 get() {
				return robotBase->GetSensorValue(0);
			}
			void set(Int32 v) {
				robotBase->SetSensorValue(0,v);
			}
		}
		property Int32 SensorS2{
			Int32 get() {
				return robotBase->GetSensorValue(1);
			}
			void set(Int32 v) {
				robotBase->SetSensorValue(1,v);
			}
		}
		property Int32 SensorS3{
			Int32 get() {
				return robotBase->GetSensorValue(2);
			}
			void set(Int32 v) {
				robotBase->SetSensorValue(2,v);
			}
		}
		property Int32 BatteryLevel {
			Int32 get() {
				return robotBase->GetBatteryLevel();
			}
			void set(Int32 v) {
				robotBase->SetBatteryLevel(v);
			}
		}

//		event System::EventHandler^ OnSetSensorMode;
		event System::EventHandler^ OnSetLightBrightness;
//		event System::EventHandler^ OnSetLightStatus;
		event System::EventHandler^ OnSendMessage;
		event System::EventHandler^ OnClearMessage;
		event System::EventHandler^ OnOrderMotor;
		event System::EventHandler^ OnCputCLCD;
		event System::EventHandler^ OnCputWLCD;
		event System::EventHandler^ OnCputSLCD;
		event System::EventHandler^ OnClearLCD;
		event System::EventHandler^ OnPlay;
		event System::EventHandler^ OnSetSoundDuration;
		event System::EventHandler^ OnSetSoundInternote;
		event System::EventHandler^ OnStopSound;
		event System::EventHandler^ OnBeepSound;
		event System::EventHandler^ OnNotifyLoopCount;

		void ShowRobotConfig()
		{
			this->textBoxA->Text = gcnew String(robotBase->GetMotorName(1));
			this->textBoxB->Text = gcnew String(robotBase->GetMotorName(2));
			this->textBoxC->Text = gcnew String(robotBase->GetMotorName(3));

			this->textBoxS1->Text = gcnew String(robotBase->GetSensorName(0));
			this->textBoxS2->Text = gcnew String(robotBase->GetSensorName(1));
			this->textBoxS3->Text = gcnew String(robotBase->GetSensorName(2));
		}

		void NotifySendMessage(Byte msg)
		{
			robotBase->SendMessageToRobot(msg);
		}

		void NotifyKeyStatus(Boolean onoff, Boolean run, Boolean view, Boolean prog)
		{
			robotBase->SetKeyStatusToRobot(onoff, run, view, prog);
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~SimulatorBaseControl()
		{
			if (components)
			{
				delete components;
			}

		}

		 delegate System::Void SetTextBoxCallback(TextBox^ tb, String^ statement);

		 private: System::Void SetTextBox(TextBox^ tb, String^ statement)
				  {
					  if (tb->InvokeRequired) {
						  SetTextBoxCallback^ d = gcnew SetTextBoxCallback(this,&SimulatorBaseControl::SetTextBox);
						  array<Object^> ^myArray = {tb,statement};

						  this->Invoke(d, myArray);
					  }
					  else {
						  tb->Text = statement;
					  }
				  }
		delegate System::Void SetLabelColorCallback(Label^ control,System::Drawing::Color color);
		private: System::Void SetLabelColor(Label^ control, Color color) {
					 if (control->InvokeRequired) {
						 SetLabelColorCallback^ d = gcnew SetLabelColorCallback(this,&SimulatorBaseControl::SetLabelColor);
						 array<Object^>^ myArray = {control, color};
						 this->Invoke(d, myArray);
					 } else {
						 control->ForeColor = color;
					 }
				 }


		void FireSetSensorMode(Int32 port, Boolean active)
		{
			String^ mode = "passive";
			if (active) {
				mode = "active";
			}
			switch (port) {
				case 0:
					this->SetTextBox(this->textBoxS1,this->textBoxS1->Text+":"+mode);
					break;
				case 1:
					this->SetTextBox(this->textBoxS2,this->textBoxS2->Text+":"+mode);
					break;
				case 2:
					this->SetTextBox(this->textBoxS3,this->textBoxS3->Text+":"+mode);
					break;
			}
		}
		void FireSetLightBrightness(Int32 port, Int32 level)
		{
			OnSetLightBrightness(this, gcnew SimulatorBase::EventArgsSetLightBrightness(port,level));
		}
		void FireSetLightStatus(Int32 port, Boolean on)
		{
			System::Drawing::Color color = System::Drawing::Color::Black;
			if (on) {
				color = System::Drawing::Color::Red;
			}
			switch (port) {
				case 0:
					this->SetLabelColor(this->labelS1, color);
					break;
				case 1:
					this->SetLabelColor(this->labelS2, color);
					break;
				case 2:
					this->SetLabelColor(this->labelS3, color);
					break;
			}
		}
		void FireSendMessage(Byte msg)
		{
			OnSendMessage(this, gcnew SimulatorBase::EventArgsSendMessage(msg));
		}

		void RegistReceiveMessageHandler(SimulatorBase::RobotBase::ReceiveMessageHandler^ handler)
		{
			robotBase->SetDelegatorReceiveMessage(handler);
		}
		void FireClearMessage(void)
		{
			OnClearMessage(this, gcnew System::EventArgs());
		}
		void FireOrderMotor(Int32 port, String^ methodName, Int32 param)
		{
			OnOrderMotor(this, gcnew SimulatorBase::EventArgsOrderMotor(port, methodName, param));
		}
		void FireCputCLCD(Int32 mode, Char c, Int32 pos)
		{
			OnCputCLCD(this, gcnew SimulatorBase::EventArgsCputCLCD(mode,c,pos));
		}
		void FireCputWLCD(UInt32 word)
		{
			OnCputWLCD(this, gcnew SimulatorBase::EventArgsCputWLCD(word));
		}
		void FireCputSLCD(String^ s)
		{
			OnCputSLCD(this, gcnew SimulatorBase::EventArgsCputSLCD(s));
		}
		void FireClearLCD(void)
		{
			OnClearLCD(this, gcnew System::EventArgs());
		}
		void FirePlay(Byte pitch, Byte length)
		{
			OnPlay(this, gcnew SimulatorBase::EventArgsPlay(pitch,length));
		}
		void FireSetSoundDuration(UInt32 len)
		{
			OnSetSoundDuration(this, gcnew SimulatorBase::EventArgsSetSoundDuration(len));
		}
		void FireSetSoundInternote(UInt32 len)
		{
			OnSetSoundInternote(this, gcnew SimulatorBase::EventArgsSetSoundInternote(len));
		}
		void FireStopSound(void)
		{
			OnStopSound(this, gcnew System::EventArgs());
		}
		void FireBeepSound(void)
		{
			OnBeepSound(this, gcnew System::EventArgs());
		}
		void FireNotiryLoopCount(UInt32 count)
		{
			OnNotifyLoopCount(this, gcnew SimulatorBase::EventArgsNotifyLoopCount(count));
		}
private: System::Windows::Forms::Label^  labelS1;
private: System::Windows::Forms::Label^  labelS2;
private: System::Windows::Forms::Label^  labelS3;


protected: 


private: System::Windows::Forms::TextBox^  textBoxS1;
private: System::Windows::Forms::TextBox^  textBoxS2;
private: System::Windows::Forms::TextBox^  textBoxS3;
private: System::Windows::Forms::Label^  label4;
private: System::Windows::Forms::Label^  label5;
private: System::Windows::Forms::Label^  label6;
private: System::Windows::Forms::TextBox^  textBoxA;
private: System::Windows::Forms::TextBox^  textBoxB;
private: System::Windows::Forms::TextBox^  textBoxC;
private: System::Windows::Forms::Label^  label7;

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>
		System::ComponentModel::Container^ components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->labelS1 = (gcnew System::Windows::Forms::Label());
			this->labelS2 = (gcnew System::Windows::Forms::Label());
			this->labelS3 = (gcnew System::Windows::Forms::Label());
			this->textBoxS1 = (gcnew System::Windows::Forms::TextBox());
			this->textBoxS2 = (gcnew System::Windows::Forms::TextBox());
			this->textBoxS3 = (gcnew System::Windows::Forms::TextBox());
			this->label4 = (gcnew System::Windows::Forms::Label());
			this->label5 = (gcnew System::Windows::Forms::Label());
			this->label6 = (gcnew System::Windows::Forms::Label());
			this->textBoxA = (gcnew System::Windows::Forms::TextBox());
			this->textBoxB = (gcnew System::Windows::Forms::TextBox());
			this->textBoxC = (gcnew System::Windows::Forms::TextBox());
			this->label7 = (gcnew System::Windows::Forms::Label());
			this->SuspendLayout();
			// 
			// labelS1
			// 
			this->labelS1->AutoSize = true;
			this->labelS1->Location = System::Drawing::Point(7, 39);
			this->labelS1->Name = L"labelS1";
			this->labelS1->Size = System::Drawing::Size(20, 12);
			this->labelS1->TabIndex = 0;
			this->labelS1->Text = L"S1:";
			// 
			// labelS2
			// 
			this->labelS2->AutoSize = true;
			this->labelS2->Location = System::Drawing::Point(7, 60);
			this->labelS2->Name = L"labelS2";
			this->labelS2->Size = System::Drawing::Size(20, 12);
			this->labelS2->TabIndex = 1;
			this->labelS2->Text = L"S2:";
			// 
			// labelS3
			// 
			this->labelS3->AutoSize = true;
			this->labelS3->Location = System::Drawing::Point(7, 85);
			this->labelS3->Name = L"labelS3";
			this->labelS3->Size = System::Drawing::Size(20, 12);
			this->labelS3->TabIndex = 2;
			this->labelS3->Text = L"S3:";
			// 
			// textBoxS1
			// 
			this->textBoxS1->Enabled = false;
			this->textBoxS1->Location = System::Drawing::Point(33, 32);
			this->textBoxS1->Name = L"textBoxS1";
			this->textBoxS1->Size = System::Drawing::Size(149, 19);
			this->textBoxS1->TabIndex = 3;
			// 
			// textBoxS2
			// 
			this->textBoxS2->Enabled = false;
			this->textBoxS2->Location = System::Drawing::Point(33, 57);
			this->textBoxS2->Name = L"textBoxS2";
			this->textBoxS2->Size = System::Drawing::Size(149, 19);
			this->textBoxS2->TabIndex = 4;
			// 
			// textBoxS3
			// 
			this->textBoxS3->Enabled = false;
			this->textBoxS3->Location = System::Drawing::Point(33, 82);
			this->textBoxS3->Name = L"textBoxS3";
			this->textBoxS3->Size = System::Drawing::Size(149, 19);
			this->textBoxS3->TabIndex = 5;
			// 
			// label4
			// 
			this->label4->AutoSize = true;
			this->label4->Location = System::Drawing::Point(7, 121);
			this->label4->Name = L"label4";
			this->label4->Size = System::Drawing::Size(15, 12);
			this->label4->TabIndex = 6;
			this->label4->Text = L"A:";
			// 
			// label5
			// 
			this->label5->AutoSize = true;
			this->label5->Location = System::Drawing::Point(7, 146);
			this->label5->Name = L"label5";
			this->label5->Size = System::Drawing::Size(15, 12);
			this->label5->TabIndex = 7;
			this->label5->Text = L"B:";
			// 
			// label6
			// 
			this->label6->AutoSize = true;
			this->label6->Location = System::Drawing::Point(7, 171);
			this->label6->Name = L"label6";
			this->label6->Size = System::Drawing::Size(15, 12);
			this->label6->TabIndex = 8;
			this->label6->Text = L"C:";
			// 
			// textBoxA
			// 
			this->textBoxA->Enabled = false;
			this->textBoxA->Location = System::Drawing::Point(33, 118);
			this->textBoxA->Name = L"textBoxA";
			this->textBoxA->Size = System::Drawing::Size(149, 19);
			this->textBoxA->TabIndex = 9;
			// 
			// textBoxB
			// 
			this->textBoxB->Enabled = false;
			this->textBoxB->Location = System::Drawing::Point(33, 143);
			this->textBoxB->Name = L"textBoxB";
			this->textBoxB->Size = System::Drawing::Size(149, 19);
			this->textBoxB->TabIndex = 10;
			// 
			// textBoxC
			// 
			this->textBoxC->Enabled = false;
			this->textBoxC->Location = System::Drawing::Point(33, 168);
			this->textBoxC->Name = L"textBoxC";
			this->textBoxC->Size = System::Drawing::Size(149, 19);
			this->textBoxC->TabIndex = 11;
			// 
			// label7
			// 
			this->label7->AutoSize = true;
			this->label7->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 12, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(128)));
			this->label7->Location = System::Drawing::Point(16, 7);
			this->label7->Name = L"label7";
			this->label7->Size = System::Drawing::Size(161, 16);
			this->label7->TabIndex = 12;
			this->label7->Text = L"Robot Configuration";
			// 
			// SimulatorBaseControl
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
			this->Controls->Add(this->label7);
			this->Controls->Add(this->textBoxC);
			this->Controls->Add(this->textBoxB);
			this->Controls->Add(this->textBoxA);
			this->Controls->Add(this->label6);
			this->Controls->Add(this->label5);
			this->Controls->Add(this->label4);
			this->Controls->Add(this->textBoxS3);
			this->Controls->Add(this->textBoxS2);
			this->Controls->Add(this->textBoxS1);
			this->Controls->Add(this->labelS3);
			this->Controls->Add(this->labelS2);
			this->Controls->Add(this->labelS1);
			this->Name = L"SimulatorBaseControl";
			this->Size = System::Drawing::Size(188, 190);
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion

		SimulatorBase::RobotBase^ robotBase;

		void UpdateRobotBase()
		{
			SimulatorBase::RobotBase::SetSensorModeHandler^ ssmFp = gcnew SimulatorBase::RobotBase::SetSensorModeHandler(this,&SimulatorBaseControl::FireSetSensorMode);
			robotBase->SetDelegatorSetSensorMode(ssmFp);

			SimulatorBase::RobotBase::SetLightBrightnessHandler^ slbFp = gcnew SimulatorBase::RobotBase::SetLightBrightnessHandler(this,&SimulatorBaseControl::FireSetLightBrightness);
			robotBase->SetDelegatorSetLightBrightness(slbFp);

			SimulatorBase::RobotBase::SetLightStatusHandler^ slsFp = gcnew SimulatorBase::RobotBase::SetLightStatusHandler(this,&SimulatorBaseControl::FireSetLightStatus);
			robotBase->SetDelegatorSetLightStatus(slsFp);

			SimulatorBase::RobotBase::SendMessageHandler^ smFp = gcnew SimulatorBase::RobotBase::SendMessageHandler(this,&SimulatorBaseControl::FireSendMessage);
			robotBase->SetDelegatorSendMessage(smFp);

			SimulatorBase::RobotBase::ClearMessageHandler^ cmFp = gcnew SimulatorBase::RobotBase::ClearMessageHandler(this,&SimulatorBaseControl::FireClearMessage);
			robotBase->SetDelegatorClearMessage(cmFp);

			SimulatorBase::RobotBase::OrderMotorHandler^ omFp = gcnew SimulatorBase::RobotBase::OrderMotorHandler(this,&SimulatorBaseControl::FireOrderMotor);
			robotBase->SetDelegatorOrderMotor(omFp);

			SimulatorBase::RobotBase::CputCLCDHandler^ cclFp = gcnew SimulatorBase::RobotBase::CputCLCDHandler(this,&SimulatorBaseControl::FireCputCLCD);
			robotBase->SetDelegatorCputCLCD(cclFp);

			SimulatorBase::RobotBase::CputWLCDHandler^ ccwFp = gcnew SimulatorBase::RobotBase::CputWLCDHandler(this,&SimulatorBaseControl::FireCputWLCD);
			robotBase->SetDelegatorCputWLCD(ccwFp);

			SimulatorBase::RobotBase::CputSLCDHandler^ ccsFp = gcnew SimulatorBase::RobotBase::CputSLCDHandler(this,&SimulatorBaseControl::FireCputSLCD);
			robotBase->SetDelegatorCputSLCD(ccsFp);

			SimulatorBase::RobotBase::ClearLCDHandler^ clFp = gcnew SimulatorBase::RobotBase::ClearLCDHandler(this,&SimulatorBaseControl::FireClearLCD);
			robotBase->SetDelegatorClearLCD(clFp);

			SimulatorBase::RobotBase::PlayHandler^ pFp = gcnew SimulatorBase::RobotBase::PlayHandler(this,&SimulatorBaseControl::FirePlay);
			robotBase->SetDelegatorPlay(pFp);

			SimulatorBase::RobotBase::SetSoundDurationHandler^ ssdFp = gcnew SimulatorBase::RobotBase::SetSoundDurationHandler(this,&SimulatorBaseControl::FireSetSoundDuration);
			robotBase->SetDelegatorSetSoundDuration(ssdFp);

			SimulatorBase::RobotBase::SetSoundInternoteHandler^ ssiFp = gcnew SimulatorBase::RobotBase::SetSoundInternoteHandler(this,&SimulatorBaseControl::FireSetSoundInternote);
			robotBase->SetDelegatorSetSoundInternote(ssiFp);

			SimulatorBase::RobotBase::StopSoundHandler^ ssFp = gcnew SimulatorBase::RobotBase::StopSoundHandler(this,&SimulatorBaseControl::FireStopSound);
			robotBase->SetDelegatorStopSound(ssFp);

			SimulatorBase::RobotBase::BeepSoundHandler^ bsFp = gcnew SimulatorBase::RobotBase::BeepSoundHandler(this,&SimulatorBaseControl::FireBeepSound);
			robotBase->SetDelegatorBeepSound(bsFp);

			SimulatorBase::RobotBase::NotifyLoopCountHandler^ nlcFp = gcnew SimulatorBase::RobotBase::NotifyLoopCountHandler(this, &SimulatorBaseControl::FireNotiryLoopCount);
			robotBase->SetDelegatorNotifyLoopCount(nlcFp);

			ShowRobotConfig();

		}

	};



}
